package com.tanhua.server.service;
import com.google.common.collect.Lists;

import com.alibaba.fastjson.JSON;
import com.tanhua.domain.db.Question;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.mongo.*;
import com.tanhua.domain.mongo.TestSoulReportVo;
import com.tanhua.dubbo.api.TestSoulApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.server.interceptor.UserHolder;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class TestSoulService {

    @Reference
    private UserInfoApi userInfoApi;

    /*@Reference //不是查mysql 是查mongodb
    private TestSoulApi testSoulApi;*/

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 接口名称：测灵魂-问卷列表（学生实战）
     * 接口路径：GET/testSoul
     */
    public ResponseEntity<Object> findByTestSoulList() {

        // 每个用户进来就设置一个表xxx_userId，每个用户都保存一个问卷3套（不需要的，只要在reportId上做文章） 用userId来区分
        Long userId = UserHolder.getUserId();
        // 查看每个用户的问卷1、2、3的reportId 从mongodb中读出来然后再设置到testSoul表中
        Query query2 = new Query(Criteria.where("UserId").is(userId.toString()));
        TestSoulReportIdAndScore reportIdAndScore = mongoTemplate.findOne(query2, TestSoulReportIdAndScore.class);
        // 如果不存在 就设置成null 将问卷id和问卷 重新设置为 001
        String reportId_1;
        String reportId_2;
        String reportId_3;
        if (reportIdAndScore == null) {
            reportId_1 = null;
            reportId_2 = null;
            reportId_3 = null;
        } else {
            reportId_1 = reportIdAndScore.getReportId_1();
            reportId_2 = reportIdAndScore.getReportId_2();
            reportId_3 = reportIdAndScore.getReportId_3();
        }

        //查TestSoulReportIdAndScore表中的isLock并且设置
        Query query1000 = new Query(Criteria.where("UserId").is(userId.toString()));
        TestSoulReportIdAndScore one = mongoTemplate.findOne(query1000, TestSoulReportIdAndScore.class);
        if (one != null) {
            // 修改testsoul表
            Query query51 = new Query(Criteria.where("_id").is("1"));
            Update update51 = new Update();
            update51.set("reportId", reportId_1);
            update51.set("isLock", 0);
            mongoTemplate.upsert(query51, update51, TestSoul.class);

            Query query52 = new Query(Criteria.where("_id").is("2"));
            Update update52 = new Update();
            update52.set("reportId", reportId_2);
            update52.set("isLock", one.getIsLock_2());
            mongoTemplate.upsert(query52, update52, TestSoul.class);

            Query query53 = new Query(Criteria.where("_id").is("3"));
            Update update53 = new Update();
            update53.set("reportId", reportId_3);
            update53.set("isLock", one.getIsLock_3());
            mongoTemplate.upsert(query53, update53, TestSoul.class);
        } else {
            // 修改testsoul表
            Query query54 = new Query(Criteria.where("_id").is("1"));
            Update update54 = new Update();
            update54.set("reportId", null);
            update54.set("isLock", 0);
            mongoTemplate.upsert(query54, update54, TestSoul.class);

            Query query55 = new Query(Criteria.where("_id").is("2"));
            Update update55 = new Update();
            update55.set("reportId", null);
            update55.set("isLock", 1);
            mongoTemplate.upsert(query55, update55, TestSoul.class);

            Query query56 = new Query(Criteria.where("_id").is("3"));
            Update update56 = new Update();
            update56.set("reportId", null);
            update56.set("isLock", 1);
            mongoTemplate.upsert(query56, update56, TestSoul.class);
        }

        

        // 创建TestSoul实体类 使用mongoTemplate来创建表 和 查询数据
        Query query = new Query();
        List<TestSoul> testSoulList = mongoTemplate.find(query, TestSoul.class);
        
        System.out.println("灵魂测试问卷内容testSoulList = " + testSoulList);
        return ResponseEntity.ok(testSoulList);
    }

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    /**
     * 接口名称：测灵魂-提交问卷（学生实战） 解锁然后变成查看报告 查看报告之后要把报告去掉 可以多次测试
     * 接口路径：POST/testSoul answers	object []  谁提交谁有报告
     */
    public ResponseEntity<Object> submitSoulQuestion(List<LinkedHashMap<String,String>> answerList) {

        // 用户id+问卷编号1+question作为key
        Long userId = UserHolder.getUserId();

        // 得出conclusion 根据分值 计算分值 猫头鹰
        int score = 0;

        //ArrayList<Answer> answersList = (ArrayList<Answer>)JSON.parseObject(jsonString, List.class);
        System.out.println("answersList = " + answerList);
        for (int i = 0; i < answerList.size(); i++) {
            LinkedHashMap<String,String> answer = answerList.get(i);

            System.out.println("answer1 = " + answer);
            String questionId = answer.get("questionId");
            String optionId = answer.get("optionId");

            // 如果qusetionId>10就取个位数，如果个位数是0就取10
            Integer questionIdInt = Integer.valueOf(questionId);
            if (questionIdInt > 10 && questionIdInt % 10 != 0) {
                questionIdInt = questionIdInt % 10;
                questionId = questionIdInt.toString();
            } else if (questionIdInt % 10 == 0) {
                questionId = "10";
            }

            Query query = new Query(Criteria.where("qid").is(questionId).and("_id").is(questionId+optionId));
            SoulOption soulOption = mongoTemplate.findOne(query, SoulOption.class);
            Integer score1 = soulOption.getScore();
            System.out.println("score1 = " + score1);
            score += score1;
        }



        // 拿到试题的第一个编号 [{"questionId":"1","optionId":"A"},{集合}]
        Map<String, String> map = (Map<String, String>) answerList.get(0);
        String questionId = map.get("questionId");


        // 查询试题的第一个编号对应的试题tid
        Query query = new Query(Criteria.where("_id").is(questionId));
        SoulQuestion soulQuestion = mongoTemplate.findOne(query, SoulQuestion.class);
        String tid = soulQuestion.getTid();






        // 将该用户和问卷对应的id存在mongoDB中 TestSoulReportIdAndScore
        if (tid.equals("1")) {
            // 保证每个用户只有一个表，没有就创建 有就修改
            Query query11 = new Query(Criteria.where("UserId").is(userId.toString()));
            Update update = new Update();
            update.set("reportId_1", "1");
            update.set("score_1", score);
            // update.set("isLock_1", 0);
            // 创建或者修改
            mongoTemplate.upsert(query11,update,TestSoulReportIdAndScore.class);
        } else if (tid.equals("2")) {
            // 保证每个用户只有一个表，没有就创建 有就修改
            Query query11 = new Query(Criteria.where("UserId").is(userId.toString()));
            Update update = new Update();
            update.set("reportId_2", "2");
            update.set("score_2", score);
            mongoTemplate.upsert(query11,update,TestSoulReportIdAndScore.class);
        } else if (tid.equals("3")) {
            // 保证每个用户只有一个表，没有就创建 有就修改
            Query query11 = new Query(Criteria.where("UserId").is(userId.toString()));
            Update update = new Update();
            update.set("reportId_3", "3");
            update.set("score_3", score);
            mongoTemplate.upsert(query11,update,TestSoulReportIdAndScore.class);
        }

        //存储对应的分数 看上面


        //将数据保存到redis中 查完报告后可以存在数据库中，还可以设置过期时间，过期了查数据库即可
        redisTemplate.opsForValue().set("userId_"+userId+"_wenjuanId_"+tid, JSON.toJSONString(score));
        System.out.println("redis的key: "+"userId_"+userId+"_wenjuanId_"+tid);

        //将soultest表中的lock值修改成解锁 isLock=0 初级tid=1 中级tid=2 tid=3的时候 就不需要把后面的问卷解锁了 后面没有问卷了
        if (Integer.valueOf(tid) <= 2) {
            Query query2 = new Query(Criteria.where("_id").is((Integer.valueOf(tid)+1)+""));
            Update update = new Update();
            update.set("isLock", 0);
            mongoTemplate.updateFirst(query2, update, TestSoul.class);

            Query query22 = new Query(Criteria.where("UserId").is(userId.toString()));

            Update update22 = new Update();
            if (tid.equals("1")) {
                update22.set("isLock_2", 0);
            } else if (tid.equals("2")) {
                update22.set("isLock_3", 0);
            }

            mongoTemplate.updateFirst(query22, update22, TestSoulReportIdAndScore.class);
        }

        // 报告id 根据分数得到的报告 报告id就是问卷编号id
        // 把soulTest表的reportId都设置成非null 说明已经做完了测试
        Query query3 = new Query(Criteria.where("_id").is(tid));
        Update update = new Update();
        update.set("reportId", tid);
        mongoTemplate.updateFirst(query3, update, TestSoul.class);


        // 新建一个返回对象
        TestSoulReport testSoulReport = new TestSoulReport();
        testSoulReport.setTid(tid);
        testSoulReport.setUserId(userId.toString());
        //testSoulReport.setId(""); 来做索引的
        //testSoulReport.setConclusion("");
        //testSoulReport.setCover("");
        //testSoulReport.setDimensions(Lists.newArrayList());
        //testSoulReport.setSimilarYou(Lists.newArrayList());

        // 设置维度数据
        ArrayList<DimensionMg> dimensionList = new ArrayList<>();
        // 最好在数据库 查这样就不用new很多的对象了 外向,判断,抽象,理性 80%,70%,90%,60%
        DimensionMg dimensionMg1 = new DimensionMg();
        dimensionMg1.setKey("外向");
        dimensionMg1.setValue("80%");
        DimensionMg dimensionMg2 = new DimensionMg();
        dimensionMg2.setKey("判断");
        dimensionMg2.setValue("70%");
        DimensionMg dimensionMg3 = new DimensionMg();
        dimensionMg3.setKey("抽象");
        dimensionMg3.setValue("90%");
        DimensionMg dimensionMg4 = new DimensionMg();
        dimensionMg4.setKey("理性");
        dimensionMg4.setValue("60%");
        dimensionList.add(dimensionMg1);
        dimensionList.add(dimensionMg2);
        dimensionList.add(dimensionMg3);
        dimensionList.add(dimensionMg4);
        testSoulReport.setDimensions(dimensionList);

        // 设置与你相似的数据
        // 先查看ReportIdAndScore表 如果有分数就推荐 切至少为4个就返回 如果没有就设置默认推荐数据

        // 把每个分数段的 随机抽出类型相似的10用户
        if (score < 21) { //猫头鹰
            // testSoulReport.setSimilarYou(owlSimilarYouList); 结果已经帮你赋值给testSoulReport对象了
            // 大于 小于
            extractedSimilarYou(0, 21, testSoulReport);

        } else if (score <= 40) { // 白兔型

            extractedSimilarYou(21,41,testSoulReport);

        } else if (score <= 55) {

            extractedSimilarYou(40,56,testSoulReport);

        } else {

            extractedSimilarYou(55, Integer.MAX_VALUE - 1, testSoulReport);

        }
        
        


        /*//redis拿出用户填的信息
        String jsonString =  redisTemplate.opsForValue().get("userId_" + userId + "_wenjuanId_" + id);
        Integer score = JSON.parseObject(jsonString, Integer.class);*/

        if (score < 21) {
            testSoulReport.setConclusion("猫头鹰：他们的共同特质为重计划、条理、细节精准。在行为上，表现出喜欢理性思考与分析、较重视制度、结构、规范。他们注重执行游戏规则、循规蹈矩、巨细靡遗、重视品质、敬业负责。");
            testSoulReport.setCover("https://tanhua-dev.oss-cn-zhangjiakou.aliyuncs.com/images/test_soul/owl.png");
        } else if (score <= 40) {
            testSoulReport.setConclusion("白兔型：平易近人、敦厚可靠、避免冲突与不具批判性。在行为上，表现出不慌不忙、冷静自持的态度。他们注重稳定与中长程规划，现实生活中，常会反思自省并以和谐为中心，即使面对困境，亦能泰然自若，从容应付。");
            testSoulReport.setCover("https://tanhua-dev.oss-cn-zhangjiakou.aliyuncs.com/images/test_soul/rabbit.png");
        } else if (score <= 55) {
            testSoulReport.setConclusion("狐狸型 ：人际关系能力极强，擅长以口语表达感受而引起共鸣，很会激励并带动气氛。他们喜欢跟别人互动，重视群体的归属感，基本上是比较「人际导向」。由于他们富同理心并乐于分享，具有很好的亲和力，在服务业、销售业、传播业及公共关系等领域中，狐狸型的领导者都有很杰出的表现。");
            testSoulReport.setCover("https://tanhua-dev.oss-cn-zhangjiakou.aliyuncs.com/images/test_soul/fox.png");
        } else {
            testSoulReport.setConclusion("狮子型：性格为充满自信、竞争心强、主动且企图心强烈，是个有决断力的领导者。一般而言，狮子型的人胸怀大志，勇于冒险，看问题能够直指核心，并对目标全力以赴。\n" +
                    "他们在领导风格及决策上，强调权威与果断，擅长危机处理，此种性格最适合开创性与改革性的工作。");
            testSoulReport.setCover("https://tanhua-dev.oss-cn-zhangjiakou.aliyuncs.com/images/test_soul/lion.png");
        }

        // 主键id自增 不会重复

        Query query100 = new Query(Criteria.where("userId").is(userId.toString()).and("tid").is(tid));

        Update update100 = new Update();
        update100.set("conclusion", testSoulReport.getConclusion());
        update100.set("cover", testSoulReport.getCover());
        update100.set("dimensions", testSoulReport.getDimensions());
        update100.set("similarYou", testSoulReport.getSimilarYou());
        mongoTemplate.upsert(query100,update100,TestSoulReport.class);

        /*// 新建一个返回对象Vo testSoulReportVo 属性要去掉id TestSoulReportVo
        TestSoulReportVo testSoulReportVo = new TestSoulReportVo();
        BeanUtils.copyProperties(testSoulReport,testSoulReportVo);*/


        return ResponseEntity.ok(tid);
    }

    /**
     * 产生SimilarYouList的方法 testSoulReport.setSimilarYou(owlSimilarYouList);
     * @param score1
     * @param score2
     * @param testSoulReport
     * @return
     */
    private void extractedSimilarYou(Integer score1,Integer score2,TestSoulReport testSoulReport) {
        Query query001 = new Query(Criteria.where("score_1").gt(score1).lt(score2));
        List<TestSoulReportIdAndScore> similar_1 = mongoTemplate.find(query001, TestSoulReportIdAndScore.class);
        List<String> list1 = similar_1.stream().map(TestSoulReportIdAndScore::getUserId).collect(Collectors.toList());
        System.out.println("list1 = " + list1);

        Query query002 = new Query(Criteria.where("score_2").gt(score1).lt(score2));
        List<TestSoulReportIdAndScore> similar_2 = mongoTemplate.find(query002, TestSoulReportIdAndScore.class);
        List<String> list2 = similar_2.stream().map(TestSoulReportIdAndScore::getUserId).collect(Collectors.toList());
        System.out.println("list2 = " + list2);

        Query query003 = new Query(Criteria.where("score_3").gt(score1).lt(score2));
        List<TestSoulReportIdAndScore> similar_3 = mongoTemplate.find(query003, TestSoulReportIdAndScore.class);
        List<String> list3 = similar_3.stream().map(TestSoulReportIdAndScore::getUserId).collect(Collectors.toList());
        System.out.println("list3 = " + list3);

        ArrayList<String> allList = new ArrayList<>();
        allList.addAll(list1);
        allList.addAll(list2);
        allList.addAll(list3);
        List<String> distinctList = allList.stream().distinct().collect(Collectors.toList());
        System.out.println("distinctList = " + distinctList);

        if (distinctList.size() >= 10) {

            ArrayList<Long> owlList = new ArrayList<>();

            // 拿10个都是猫头鹰类型的用户userId long类型

            for (int i = 0; i < 10; i++) {
                int i1 = new Random().nextInt(distinctList.size());
                owlList.add(Long.valueOf(distinctList.get(i1)));
                distinctList.remove(i1);
            }

            ArrayList<SimilarYou> owlSimilarYouList = new ArrayList<>();

            // 把10个用户放到集合中
            SimilarYou similarYou01 = new SimilarYou();
            similarYou01.setId(Integer.valueOf(owlList.get(0).toString()));
            UserInfo userInfo1 = userInfoApi.findById(Long.valueOf(owlList.get(0).toString()));
            String avatar1 = userInfo1.getAvatar();
            similarYou01.setAvatar(avatar1);
            owlSimilarYouList.add(similarYou01);

            SimilarYou similarYou02 = new SimilarYou();
            similarYou02.setId(Integer.valueOf(owlList.get(1).toString()));
            UserInfo userInfo2 = userInfoApi.findById(Long.valueOf(owlList.get(1).toString()));
            String avatar2 = userInfo2.getAvatar();
            similarYou02.setAvatar(avatar2);
            owlSimilarYouList.add(similarYou02);

            SimilarYou similarYou03 = new SimilarYou();
            similarYou03.setId(Integer.valueOf(owlList.get(2).toString()));
            UserInfo userInfo3 = userInfoApi.findById(Long.valueOf(owlList.get(2).toString()));
            String avatar3 = userInfo3.getAvatar();
            similarYou03.setAvatar(avatar3);
            owlSimilarYouList.add(similarYou03);

            SimilarYou similarYou04 = new SimilarYou();
            similarYou04.setId(Integer.valueOf(owlList.get(3).toString()));
            UserInfo userInfo4 = userInfoApi.findById(Long.valueOf(owlList.get(3).toString()));
            String avatar4 = userInfo4.getAvatar();
            similarYou04.setAvatar(avatar4);
            owlSimilarYouList.add(similarYou04);

            SimilarYou similarYou05 = new SimilarYou();
            similarYou05.setId(Integer.valueOf(owlList.get(4).toString()));
            UserInfo userInfo5 = userInfoApi.findById(Long.valueOf(owlList.get(4).toString()));
            String avatar5 = userInfo5.getAvatar();
            similarYou05.setAvatar(avatar5);
            owlSimilarYouList.add(similarYou05);

            SimilarYou similarYou06 = new SimilarYou();
            similarYou06.setId(Integer.valueOf(owlList.get(5).toString()));
            UserInfo userInfo6 = userInfoApi.findById(Long.valueOf(owlList.get(5).toString()));
            String avatar6 = userInfo6.getAvatar();
            similarYou06.setAvatar(avatar6);
            owlSimilarYouList.add(similarYou06);

            SimilarYou similarYou07 = new SimilarYou();
            similarYou07.setId(Integer.valueOf(owlList.get(6).toString()));
            UserInfo userInfo7 = userInfoApi.findById(Long.valueOf(owlList.get(6).toString()));
            String avatar7 = userInfo7.getAvatar();
            similarYou07.setAvatar(avatar7);
            owlSimilarYouList.add(similarYou07);

            SimilarYou similarYou08 = new SimilarYou();
            similarYou08.setId(Integer.valueOf(owlList.get(7).toString()));
            UserInfo userInfo8 = userInfoApi.findById(Long.valueOf(owlList.get(7).toString()));
            String avatar8 = userInfo8.getAvatar();
            similarYou08.setAvatar(avatar8);
            owlSimilarYouList.add(similarYou08);

            SimilarYou similarYou09 = new SimilarYou();
            similarYou09.setId(Integer.valueOf(owlList.get(8).toString()));
            UserInfo userInfo9 = userInfoApi.findById(Long.valueOf(owlList.get(8).toString()));
            String avatar9 = userInfo9.getAvatar();
            similarYou09.setAvatar(avatar9);
            owlSimilarYouList.add(similarYou09);

            testSoulReport.setSimilarYou(owlSimilarYouList);

        } else { //只能设置成10个或者4个了 4个也可以的

            // 设置与你相似的数据
            ArrayList<SimilarYou> SimilarYouList = new ArrayList<>();
            // 最好在数据库 查这样就不用new很多的对象了 外向,判断,抽象,理性 80%,70%,90%,60%
            SimilarYou similarYou1 = new SimilarYou();
            similarYou1.setId(1);
            similarYou1.setAvatar("https://tanhua-dev.oss-cn-zhangjiakou.aliyuncs.com/images/tanhua/avatar_1.png");

            SimilarYou similarYou2 = new SimilarYou();
            similarYou2.setId(2);
            similarYou2.setAvatar("https://tanhua-dev.oss-cn-zhangjiakou.aliyuncs.com/images/tanhua/avatar_2.png");

            SimilarYou similarYou3 = new SimilarYou();
            similarYou3.setId(3);
            similarYou3.setAvatar("https://tanhua-dev.oss-cn-zhangjiakou.aliyuncs.com/images/tanhua/avatar_3.png");

            SimilarYou similarYou4 = new SimilarYou();
            similarYou4.setId(4);
            similarYou4.setAvatar("https://tanhua-dev.oss-cn-zhangjiakou.aliyuncs.com/images/tanhua/avatar_4.png");

            SimilarYouList.add(similarYou1);
            SimilarYouList.add(similarYou2);
            SimilarYouList.add(similarYou3);
            SimilarYouList.add(similarYou4);
            testSoulReport.setSimilarYou(SimilarYouList);

        }
    }

    /**
     * 接口名称：测灵魂-查看结果（学生实战）
     * 接口路径：GET/testSoul/report/:id
     */
    public ResponseEntity<Object> readReport(String id) {

        Long userId = UserHolder.getUserId();

        // 先查redis/mongobd中 存一个testsoulreport表 如果有直接查看 如果没有就重新设置



        // 查看是否已经存在该（初级）问卷是否存在，存在了直接返回数据，然后return 否则就重新计算分数 upsert修改/第一次是添加 每次查看查数据库比你重新计算效率高
        Query query = new Query(Criteria.where("tid").is(id).and("userId").is(userId.toString()));
        TestSoulReport testSoulReport = mongoTemplate.findOne(query, TestSoulReport.class);



        // 将该用户和问卷对应的id存在mongoDB中 TestSoulReportIdAndScore
        if (id.equals("1")) {

            extractedSetSimlilarYouList(userId, testSoulReport);

        } else if (id.equals("2")) {

            // 保证每个用户只有一个表，没有就创建 有就修改
            extractedSetSimlilarYouList(userId, testSoulReport);

        } else if (id.equals("3")) {

            // 保证每个用户只有一个表，没有就创建 有就修改
            extractedSetSimlilarYouList(userId, testSoulReport);

        }

        TestSoulReportVo testSoulReportVo1 = new TestSoulReportVo();
        BeanUtils.copyProperties(testSoulReport,testSoulReportVo1);

        return ResponseEntity.ok(testSoulReportVo1);


    }

    /**
     * 替换与你相似
     * @param userId
     * @param testSoulReport
     */
    private void extractedSetSimlilarYouList(Long userId, TestSoulReport testSoulReport) {
        // 保证每个用户只有一个表，没有就创建 有就修改
        Query query11 = new Query(Criteria.where("UserId").is(userId.toString()));
        // update.set("isLock_1", 0);
        // 创建或者修改
        TestSoulReportIdAndScore zero1 = mongoTemplate.findOne(query11, TestSoulReportIdAndScore.class);

        Integer score = zero1.getScore_1();

        // 把每个分数段的 随机抽出类型相似的10用户
        if (score < 21) { //猫头鹰
            // testSoulReport.setSimilarYou(owlSimilarYouList); 结果已经帮你赋值给testSoulReport对象了
            // 大于 小于
            extractedSimilarYou(0, 21, testSoulReport);

        } else if (score <= 40) { // 白兔型

            extractedSimilarYou(21, 41, testSoulReport);

        } else if (score <= 55) {

            extractedSimilarYou(40, 56, testSoulReport);

        } else {

            extractedSimilarYou(55, Integer.MAX_VALUE - 1, testSoulReport);

        }
    }
}
